﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace HoldemGame
{

    public class CardValue : IComparable<CardValue>
    {
        private double _value;
        public static CardValue Invalid = new CardValue(double.NaN);


        public double Value { get { return _value; } set { _value = value; } }
        
        
        public CardValue(double value)
        {
            _value = value;
        }

        public static CardValue Parse(string input)
        {
            return new CardValue(double.Parse(input));
        }

        #region IComparable<CardSet> Members

        public virtual int CompareTo(CardValue other)
        {
            if (this == other)
                return 0;
            if (this.Value > other.Value)
                return 1;
            if (this.Value < other.Value)
                return -1;
            return 0;
        }

        public override string ToString()
        {
            return string.Format("Z={0:F3}",Value);
        }

        #endregion

    }

    public abstract class CardStrength
    {
        public abstract CardValue ValueOf(ICardSet cs);
        public abstract ICardSetList FromValue(CardValue value);
    }


    public class CardSetRecord : IComparable<CardSetRecord>
    {
        class CardSetRecordComparer : IComparer<CardSetRecord>
        {
            #region IComparer<CardSetRecord> Members

            public int Compare(CardSetRecord x, CardSetRecord y)
            {
                if ((x == null) || (y == null))
                    return 1;
                return x.CompareTo(y);
            }

            #endregion
        }

        public static IComparer<CardSetRecord> ByValueComparer { get { return new CardSetRecordComparer(); } }

        public CardValue Value{get;set;}
        public ICardSetList Cards{get;set;}

        public CardSetRecord(ICardSetList cards, CardValue value)
        {
            Cards = cards;
            Value = value;
        }
    
        #region IComparable<CardSetRecord> Members

        public int  CompareTo(CardSetRecord other)
        {
 	        return this.Value.CompareTo(other.Value);
        }

        #endregion
    }

    public class TabularCardStrength : CardStrength
    {
        private IList<CardSetRecord> _list = Layers.Factory.NewSortedList<CardSetRecord>(CardSetRecord.ByValueComparer);

        public TabularCardStrength()
        {
        }

        public TabularCardStrength(string file)
        {
            Read(file);
        }

        public void Read(string file)
        {
            StreamReader sr = new StreamReader(file);
            CardStrengthFormatter csf = new CardStrengthFormatter();
            csf.Read(this, sr);
            sr.Close();
        }

        public void Write(string file)
        {
            StreamWriter sr = new StreamWriter(file);
            CardStrengthFormatter csf = new CardStrengthFormatter();
            csf.Write(this, sr);
            sr.Close();
        }

        public override CardValue ValueOf(ICardSet cs)
        {
            for(int i=0;i<_list.Count;i++)
            {
                if (_list[i].Cards.Contains(cs))
                    return _list[i].Value;
            }
            return CardValue.Invalid;
        }

        public override ICardSetList FromValue(CardValue value)
        {
            for (int i = 0; i < _list.Count; i++)
            {
                if (_list[i].Value.CompareTo(value)<=0
                    && (i+1>=_list.Count || _list[i+1].Value.CompareTo(value)>0))
                        return _list[i].Cards;
            }
            return null;
        }

        public virtual void Add(ICardSetList cs, CardValue val)
        {
            _list.Add(new CardSetRecord(cs, val));
        }

        public int Count { get { return _list.Count; } }

        public CardSetRecord this[int i] { get { return _list[i]; } }
    }

    public class CardStrengthFormatter
    {
        public virtual void Read(TabularCardStrength cstr, TextReader rdr)
        {
            string line = null;
            while((line=rdr.ReadLine())!=null)
            {
                string[] valuecards = line.Split(':');
                if (valuecards.Length < 2)
                    throw new InvalidOperationException("Line format\nValue:Cards");
                CardValue value = CardValue.Parse(valuecards[0]);
                CardSetList cards = CardSetList.Parse(valuecards[1]);
                cstr.Add(cards, value);
            }
        }

        public virtual void Write(TabularCardStrength cstr, TextWriter wr)
        {
            for (int i = 0; i < cstr.Count; i++)
                wr.WriteLine("{0:F3}:  {1}", cstr[i].Value.Value, cstr[i].Cards.ToString());
        }
    }


}